home *** CD-ROM | disk | FTP | other *** search
/ Underground / Underground CD1.iso / virii / zrodla / d / diskscan.asm < prev    next >
Encoding:
Assembly Source File  |  1998-01-14  |  10.5 KB  |  304 lines

  1. ;    DISKSCAN.ASM -- Checks out disk by reading sectors
  2.  
  3. ;    --------------------------------------------------
  4.  
  5.  
  6.  
  7. CSEG        Segment
  8.  
  9.         Assume    CS:CSEG, DS:CSEG, ES:CSEG, SS:CSEG
  10.  
  11.         Org    100h
  12.  
  13. Entry:        Jmp    Begin
  14.  
  15.  
  16.  
  17. ;    All Data
  18.  
  19. ;    --------
  20.  
  21.                 db    ' Copyright 1986 Ziff-Davis Publishing Co.'
  22.  
  23.         db    ' Programmed by Charles Petzold '
  24.  
  25. DriveError    db    'Invalid Drive$'
  26.  
  27. DosVersErr    db    'Needs DOS 2.0+$'
  28.  
  29. MemoryError    db    'Needs 64K$'
  30.  
  31. ReadSegment    dw    ?
  32.  
  33. DriveNum    db    ?
  34.  
  35. DiskBlock    db    18 dup (?)
  36.  
  37. TotalSectors    dw    ?
  38.  
  39. SectorsIn64K    dw    ?
  40.  
  41. StartSector    dw    0
  42.  
  43. SectorLabel2    db    9,'Sector $' 
  44.  
  45. SectorLabel    db    13,'Sectors $'
  46.  
  47. DashLabel    db    ' - $'
  48.  
  49. ErrorLabel    db    ': Error!'
  50.  
  51. CRLF        db    13,10,'$'
  52.  
  53. ErrorAddr    dw    Err0,Err1,Err2,Err3,Err4,Err5,Err6,Err7
  54.  
  55.         dw    Err8,Err9,ErrA,ErrB,ErrC,ErrD,ErrD,ErrD  
  56.  
  57. Err0        db    'Write Protect$'
  58.  
  59. Err1        db    'Unknown Unit$'
  60.  
  61. Err2        db    'Drive Not Ready$'
  62.  
  63. Err3        db    'Unknown Command$'
  64.  
  65. Err4        db    'CRC Error$'
  66.  
  67. Err5        db    'Request Length$'
  68.  
  69. Err6        db    'Seek Error$'
  70.  
  71. Err7        db    'Unknown Media$'
  72.  
  73. Err8        db    'Sector Not Found$'
  74.  
  75. Err9        db    'No Paper$'
  76.  
  77. ErrA        db    'Write Fault$'
  78.  
  79. ErrB        db    'Read Fault$'
  80.  
  81. ErrC        db    'General Failure$'
  82.  
  83. ErrD        db    'Undocumented Error$'
  84.  
  85. BootSectMsg    db    'Boot Sector$'
  86.  
  87. RootDirMsg    db    'Root Directory$'
  88.  
  89. BadFatMsg    db    'File Alloc. Table$'
  90.  
  91. InUseMsg    db    'Used by file$'
  92.  
  93. NotInUseMsg    db    'Unallocated$'
  94.  
  95. BadFlagMsg    db    'Flagged as bad$'    
  96.  
  97. FatReadMsg    db    "Can't Read FAT$"
  98.  
  99. Divisors    dw    10000, 1000, 100, 10, 1    ; For decimal conversion
  100.  
  101.  
  102.  
  103. ;    Check Drive Parameter, DOS Version, and Enough Memory
  104.  
  105. ;    -----------------------------------------------------
  106.  
  107.  
  108.  
  109. ErrorExit:    Mov    AH,9        ; Write error message
  110.  
  111.         Int    21h        ;      through DOS
  112.  
  113.         Int    20h        ; And terminate
  114.  
  115.  
  116.  
  117. Begin:        Mov    DX, Offset DriveError    ; Possible message
  118.  
  119.         Or    AL, AL        ; Check Drive Validity Byte
  120.  
  121.         Jnz    ErrorExit    ; If not zero, invalid drive
  122.  
  123.         Mov    DX, Offset DosVersErr    ; Possible message
  124.  
  125.         Mov    AH, 30h
  126.  
  127.         Int    21h        ; Get DOS Version Number
  128.  
  129.         Cmp    AL, 2        ; Check for 2.0 or later
  130.  
  131.         Jb    ErrorExit    ; If not, terminate with message 
  132.  
  133.         Mov    DX, Offset MemoryError    ; Possible error message
  134.  
  135.         Mov    BX, 256+Offset EndProg    ; Set beyond program 
  136.  
  137.         Mov    SP, BX        ; Move stack closer to code
  138.  
  139.         Add    BX, 15        ; Add 15 to round up
  140.  
  141.         Mov    CL, 4        ; Divide BX by 16
  142.  
  143.         Shr    BX, CL
  144.  
  145.         Mov    AH, 4Ah        ; Free allocated memory
  146.  
  147.         Int    21h        ;   by calling DOS Set Block
  148.  
  149.         Jc    ErrorExit    ; Terminate on error
  150.  
  151.         Mov    BX, 1000h    ; Ask for 64K bytes
  152.  
  153.         Mov    AH, 48h        ;   by using DOS
  154.  
  155.         Int    21h        ;   Allocate Memory call
  156.  
  157.         Jc    ErrorExit    ; Terminate on error
  158.  
  159.         Mov    [ReadSegment], AX    ; Save segment of memory block
  160.  
  161.  
  162.  
  163. ;    Get Disk Information From DOS
  164.  
  165. ;    -----------------------------
  166.  
  167.  
  168.  
  169.         Mov    DL, DS:[005Ch]    ; Get Drive Parameter
  170.  
  171.         Push    DS        ; Save DS
  172.  
  173.         Mov    AH, 32h        ; Call DOS to
  174.  
  175.         Int    21h        ;   get DOS Disk Block (DS:BX)
  176.  
  177.         Mov    SI, BX        ; Now DS:SI points to Disk Block
  178.  
  179.         Mov    DI, Offset DiskBlock    ; DI points to destination
  180.  
  181.         Mov    CX, 18        ; 18 bytes to copy'
  182.  
  183.         Cld            ; Forward direction
  184.  
  185.         Rep    Movsb        ; Move 'em in
  186.  
  187.         Pop    DS        ; Get back DS
  188.  
  189.         Mov    BX, Offset DiskBlock    ; BX to address Disk Block 
  190.  
  191.         Mov    DX, 1        ; Set DX:AX to 65,536
  192.  
  193.         Sub    AX, AX
  194.  
  195.         Div    Word Ptr [BX + 2]    ; Divide by Bytes Per Sector
  196.  
  197.         Mov    [SectorsIn64K], AX    ; Save that values
  198.  
  199.         Mov    AX, [BX + 13]        ; Last Cluster Number
  200.  
  201.         Dec    AX            ; AX = Number of Clusters
  202.  
  203.         Mov    CL, [BX + 5]        ; Cluster to Sector Shift
  204.  
  205.         Shl    AX, CL            ; AX = Number Data Sectors
  206.  
  207.         Add    AX, [BX + 11]        ; Add First Data Sector
  208.  
  209.         Mov    [TotalSectors], AX    ; AX = Number Total Sectors
  210.  
  211.         Mov    AL, DS:[005Ch]    ; Drive Number (0=def, 1=A)
  212.  
  213.         Dec    AL        ; Make it 0=A, 1=B
  214.  
  215.         Jns    GotDriveNumber    ; If no sign, not default drive
  216.  
  217.         Mov    AH, 19h        ; Get current disk 
  218.  
  219.         Int    21h        ;   by calling DOS
  220.  
  221.  
  222.  
  223. GotDriveNumber:    Mov    [DriveNum], AL    ; Save Drive Number (0=A, 1=B)
  224.  
  225.  
  226.  
  227. ;    Start Reading
  228.  
  229. ;    -------------    
  230.  
  231.  
  232.  
  233. MainLoop:    Mov    DX, Offset SectorLabel    ; String to display on screen
  234.  
  235.         Call    StringWrite        ; Display it
  236.  
  237.         Mov    AX, [StartSector]    ; Starting sector number
  238.  
  239.         Call    WordWrite        ; Display number on screen
  240.  
  241.         Mov    DX, Offset DashLabel    ; String containing a dash
  242.  
  243.         Call    StringWrite        ; Display it on the screen
  244.  
  245.         Mov    CX, [SectorsIn64K]    ; Number of sectors to read
  246.  
  247.         Add    AX, CX            ; Add it to starting sector
  248.  
  249.         Jc    NumRecalc
  250.  
  251.         Cmp    AX, [TotalSectors]    ; See if bigger than total
  252.  
  253.         Jbe    NumSectorsOK        ; If so, proceed
  254.  
  255.  
  256.  
  257. NumRecalc:    Mov    AX, [TotalSectors]    ; Otherwise get total sectors
  258.  
  259.         Mov    CX, AX            ; Move it to CX also
  260.  
  261.         Sub    CX, [StartSector]    ; Now CX = sectors to read
  262.  
  263.  
  264.  
  265. NumSectorsOK:    Dec    AX            ; AX = last sector to read
  266.  
  267.         Call    WordWrite        ; Display it on screen
  268.  
  269.         Call    ReadSectors        ; Read the sectors
  270.  
  271.         Jnc    NextSectors        ; If no error, skip detail
  272.  
  273.         Call    ReadSectors        ; Repeat read
  274.  
  275.         Jnc    NextSectors        ; If still no error, skip
  276.  
  277.  
  278.  
  279. DiskError:    Mov    DX, Offset ErrorLabel    ; String saying "Error!"
  280.  
  281.         Call    StringWrite        ; Display it on screen
  282.  
  283.  
  284.  
  285. ErrorLoop:    Push    CX            ; Now save previous number
  286.  
  287.         Mov    CX, 1            ; So we can read one at a time
  288.  
  289.         Call    ReadSectors        ; Read one sector
  290.  
  291.         Jnc    NoError            ; If no error, proceed
  292.  
  293.         Mov    BL, AL            ; Save error code
  294.  
  295.         Mov    DX, Offset SectorLabel2    ; String with "Sector "
  296.  
  297.         Call    StringWrite        ; Display it on screen
  298.  
  299.         Mov    AX, [StartSector]    ; The sector we just read
  300.  
  301.         Call    WordWrite        ; Display it on screen
  302.  
  303.         Mov    DX, Offset DashLabel    ; String with a dash
  304.  
  305.         Call    StringWrite        ; Display it on screen
  306.  
  307.         And    BL, 0Fh            ; Blank out error top bits
  308.  
  309.         Sub    BH, BH            ; Now BX is error code
  310.  
  311.         Add    BX, BX            ; Double it for word access
  312.  
  313.         Mov    DX, [ErrorAddr + BX]    ; Get address of message
  314.  
  315.         Call    StringWrite        ; Display message on screen
  316.  
  317.         Call    FindSector        ; See where sector is 
  318.  
  319.         Mov    DX, Offset CRLF        ; String for new line 
  320.  
  321.         Call    StringWrite        ; Do carriage ret & line feed 
  322.  
  323.  
  324.  
  325. NoError:    Inc    [StartSector]        ; Kick up the start sector
  326.  
  327.         Pop    CX            ; Get back counter
  328.  
  329.         Loop    ErrorLoop        ; And read next sector
  330.  
  331.         Mov    AX, [StartSector]    ; Sector of next group
  332.  
  333.         Jmp    Short CheckFinish    ; Check if at end yet
  334.  
  335.  
  336.  
  337. NextSectors:    Mov    AX, [StartSector]    ; For no error, increment 
  338.  
  339.         Add    AX, [SectorsIn64K]    ;   StartSector for next group
  340.  
  341.         Jc    Terminate        ; (If overflow, terminate)
  342.  
  343.         Mov    [StartSector], AX    ; And save it
  344.  
  345.  
  346.  
  347. CheckFinish:    Cmp    AX, [TotalSectors]    ; See if at then end
  348.  
  349.         Jae    Terminate        ; If so, just terminate
  350.  
  351.         Jmp    MainLoop        ; If not, do it again
  352.  
  353.  
  354.  
  355. Terminate:    Int    20h            ; Terminate
  356.  
  357.  
  358.  
  359. ;    Find Sector in FAT to see if used by file, etc.
  360.  
  361. ;    -----------------------------------------------
  362.  
  363.  
  364.  
  365. FindSector:    Mov    DX, Offset DashLabel        ; Print dash
  366.  
  367.         Call    StringWrite
  368.  
  369.         Mov    AX, [StartSector]        ; Sector with error
  370.  
  371.         Mov    DX, Offset BootSectMsg        ; Set up message
  372.  
  373.         Cmp    AX, Word Ptr [DiskBlock + 6]    ; See if sector boot
  374.  
  375.         Jb    PrintMsg            ; If so, print as such
  376.  
  377.         Mov    DX, Offset BadFatMsg        ; Set up message
  378.  
  379.         Cmp    AX, Word Ptr [DiskBlock + 16]    ; See if sector in FAT
  380.  
  381.          Jb    PrintMsg            ; If so, print as such
  382.  
  383.         Mov    DX, Offset RootDirMsg        ; Set up message
  384.  
  385.         Cmp    AX, Word Ptr [DiskBlock + 11]    ; See if sector in dir
  386.  
  387.         Jb    PrintMsg            ; If so, print as such
  388.  
  389.         Push    [StartSector]            ; Save the sector
  390.  
  391.         Mov    AX, Word Ptr [DiskBlock + 6]    ; Reserved sectors
  392.  
  393.         Mov    [StartSector], AX        ; Start of first FAT
  394.  
  395.         Mov    CL, [DiskBlock + 15]        ; Sectors for FAT
  396.  
  397.         Sub    CH, CH                ; Zero out top byte        
  398.  
  399.         Call    ReadSectors            ; Read in FAT
  400.  
  401.         Pop    [StartSector]            ; Get back bad sector
  402.  
  403.         Mov    DX, Offset FatReadMsg        ; Set up possible msg
  404.  
  405.         Jc    PrintMsg            ; If read error, print
  406.  
  407.         Mov    AX, [StartSector]        ; Get bad sector
  408.  
  409.         Sub    AX, Word Ptr [DiskBlock + 11]    ; Subtract data start
  410.  
  411.         Mov    CL, [DiskBlock + 5]        ; Sector Shift
  412.  
  413.         Shr    AX, CL                ; Shift the sector
  414.  
  415.         Add    AX, 2                ; AX is now cluster
  416.  
  417.         Push    ES            ; Save ES for awhile                
  418.  
  419.         Mov    ES, [ReadSegment]    ; ES segment of FAT
  420.  
  421.         Cmp    Word Ptr [DiskBlock + 13], 0FF0h; 12 or 16-bit FAT?
  422.  
  423.         Jge    Fat16Bit        ; And jump accordingly
  424.  
  425.         Mov    BX, AX            ; This is cluster number
  426.  
  427.         Mov    SI, AX            ; So is this
  428.  
  429.         Shr    BX, 1            ; This is one-half cluster
  430.  
  431.         Mov    AX, ES:[BX + SI]    ; BX + SI = 1.5 CX
  432.  
  433.         Jnc    NoShift            ; If no CY from shift, got it
  434.  
  435.         Mov    CL, 4            ; If CY from shift must
  436.  
  437.         Shr    AX, CL            ;   shift word 4 bits right
  438.  
  439.  
  440.  
  441. NoShift:    Or    AX, 0F000h        ; Now put 1's in top bits
  442.  
  443.         Cmp    AX, 0F000h        ; See if zero otherwise
  444.  
  445.         Jmp    Short CheckWord        ; And continue checking
  446.  
  447.  
  448.  
  449. Fat16Bit:    Mov    BX, AX            ; This is cluster number
  450.  
  451.         Shl    BX, 1            ; Double it
  452.  
  453.         Mov    AX, ES:[BX]        ; Pull out word from sector
  454.  
  455.         Or    AX, AX            ; See if zero (unallocated)
  456.  
  457.  
  458.  
  459. CheckWord:    Pop    ES            ; Get back ES
  460.  
  461.         Mov    DX, Offset NotInUseMsg    ; Set up possible message
  462.  
  463.         Jz    PrintMsg        ; If so, print message
  464.  
  465.         Mov    DX, Offset BadFlagMsg    ; Set up possible message
  466.  
  467.         Cmp    AX, 0FFF7h        ; See if cluster flagged bad
  468.  
  469.         Jz    PrintMsg        ; If so, print message
  470.  
  471.         Mov    DX, Offset InUseMsg    ; If not, cluster is in use
  472.  
  473.  
  474.  
  475. PrintMsg:    Call    StringWrite        ; Print cluster disposition
  476.  
  477.         Ret                ; And return
  478.  
  479.  
  480.  
  481. ;    Read Sectors (CX = Number of Sectors, Return CY and AL for error)
  482.  
  483. ;    -----------------------------------------------------------------
  484.  
  485.  
  486.  
  487. ReadSectors:    Push    BX            ; Push all needed registers
  488.  
  489.         Push    CX
  490.  
  491.         Push    DX
  492.  
  493.         Push    DS
  494.  
  495.         Mov    AL, [DriveNum]        ; Get the drive number code
  496.  
  497.         Sub    BX, BX            ; Buffer address offset
  498.  
  499.         Mov    DX, [StartSector]    ; Starting Sector
  500.  
  501.         Mov    DS, [ReadSegment]    ; Buffer address segment
  502.  
  503.         Int    25h            ; Absolute Disk Read
  504.  
  505.         Pop    BX            ; Fix up stack
  506.  
  507.         Pop    DS            ; Get back registers
  508.  
  509.         Pop    DX
  510.  
  511.         Pop    CX
  512.  
  513.         Pop    BX
  514.  
  515.         Ret                ; Return to program 
  516.  
  517.  
  518.  
  519. ;    Screen Display Routines
  520.  
  521. ;    -----------------------
  522.  
  523.  
  524.  
  525. WordWrite:    Push    AX            ; Push some registers
  526.  
  527.         Push    BX            ; AX contains word to display
  528.  
  529.         Push    CX
  530.  
  531.         Push    DX
  532.  
  533.         Push    SI
  534.  
  535.         Mov    SI, Offset Divisors    ; SI points to divisors
  536.  
  537.         Mov    CX, 4            ; CL counter; CH zero blanker 
  538.  
  539.  
  540.  
  541. WordWriteLoop:    Mov    BX, [SI]        ; Get divisor 
  542.  
  543.         Add    SI, 2            ; Increment SI for next one
  544.  
  545.         Sub    DX, DX            ; Prepare for division
  546.  
  547.         Div    BX            ; Divide DX:AX by BX
  548.  
  549.         Push    DX            ; Save remainder
  550.  
  551.         Or    CH, AL            ; See if zero
  552.  
  553.         Jz    LeadZero        ; If so, do not display it
  554.  
  555.         Add    AL, '0'            ; Convert number to ASCII
  556.  
  557.         Mov    DL, AL            ; Print out character
  558.  
  559.         Mov    AH, 2            ;   by calling DOS
  560.  
  561.         Int    21h
  562.  
  563.  
  564.  
  565. LeadZero:    Pop    AX            ; Get back remainder
  566.  
  567.         Dec    CL            ; Decrement counter
  568.  
  569.         Jg    WordWriteLoop        ; If CL still > 0, do it again
  570.  
  571.         Mov    CH, 1            ; No more zero blanking
  572.  
  573.         Jz    WordWriteLoop        ; Convert last digit to ASCII
  574.  
  575.         Pop    SI            ; Get back pushed registers
  576.  
  577.         Pop    DX
  578.  
  579.         Pop    CX
  580.  
  581.         Pop    BX
  582.  
  583.         Pop    AX
  584.  
  585.         Ret
  586.  
  587.  
  588.  
  589. StringWrite:    Push    AX            ; Displays string from DX
  590.  
  591.         Mov    AH, 9            ;   to screen by calling DOS
  592.  
  593.         Int    21h
  594.  
  595.         Pop    AX
  596.  
  597.         Ret
  598.  
  599.  
  600.  
  601. EndProg        Label    Byte            ; End of program
  602.  
  603. CSEG        EndS
  604.  
  605.         End    Entry
  606.  
  607.